<template><div><p>本文档最新版为 <a href="https://learnku.com/docs/laravel/10.x" target="_blank" rel="noopener noreferrer">10.x</a>，旧版本可能放弃维护，推荐阅读最新版！</p>
<h2 id="laravel-的远程服务器任务处理器-envoy" tabindex="-1"><a class="header-anchor" href="#laravel-的远程服务器任务处理器-envoy"><span>Laravel 的远程服务器任务处理器 Envoy</span></a></h2>
<ul>
<li><a href="#introduction">简介</a>
<ul>
<li><a href="#installation">安装</a></li>
</ul>
</li>
<li><a href="#writing-tasks">编写任务</a>
<ul>
<li><a href="#setup">任务启动</a></li>
<li><a href="#variables">任务变量</a></li>
<li><a href="#stories">任务故事</a></li>
<li><a href="#multiple-servers">多个服务器</a></li>
</ul>
</li>
<li><a href="#running-tasks">运行任务</a>
<ul>
<li><a href="#confirming-task-execution">任务确认</a></li>
</ul>
</li>
<li><a href="#notifications">通知</a>
<ul>
<li><a href="#slack">Slack</a></li>
</ul>
</li>
</ul>
<h2 id="简介" tabindex="-1"><a class="header-anchor" href="#简介"><span>简介</span></a></h2>
<p><a href="https://github.com/laravel/envoy" target="_blank" rel="noopener noreferrer">Laravel Envoy</a> 为定义在远程服务器上运行的通用任务提供了一种简洁、轻便的语法。它使用了 Blade 风格的语法，让你可以很方便的启动任务来进行项目部署、Artisan 命令运行等操作。目前，Envoy 只支持 Mac 及 Linux 操作系统。</p>
<h3 id="安装" tabindex="-1"><a class="header-anchor" href="#安装"><span>安装</span></a></h3>
<p>首先，使用 Composer <code v-pre>global require</code> 命令来安装 Enovy ：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line">composer <span class="token keyword">global</span> <span class="token keyword">require</span> laravel<span class="token operator">/</span>envoy</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>因为 Composer 的全局库有时会导致包的版本冲突，所以你可以考虑使用 <code v-pre>cgr</code> ，它是 <code v-pre>composer global require</code> 命令的一种替代实现 <code v-pre>cgr</code> 库的安装指导可以在 <a href="https://github.com/consolidation-org/cgr" target="_blank" rel="noopener noreferrer">GitHub上找到</a>。</p>
<blockquote>
<p>{note} 一定要确保 <code v-pre>~/.composer/vendor/bin</code> 目录加入到了你的 PATH 中，这样才能在命令行运行 <code v-pre>envoy</code> 。</p>
</blockquote>
<h4 id="更新-envoy" tabindex="-1"><a class="header-anchor" href="#更新-envoy"><span>更新 Envoy</span></a></h4>
<p>你也可以使用 Composer 来更新 Envoy 到最新版本。 要注意 <code v-pre>composer global update</code> 命令是更新你所有在全局安装的包：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line">composer <span class="token keyword">global</span> update</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><h2 id="编写任务" tabindex="-1"><a class="header-anchor" href="#编写任务"><span>编写任务</span></a></h2>
<p>所有的 Envoy 任务都必须定义在项目根目录的 <code v-pre>Envoy.blade.php</code> 文件中，这里有个例子：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line">@<span class="token function">servers</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token string single-quoted-string">'web'</span> <span class="token operator">=></span> <span class="token punctuation">[</span><span class="token string single-quoted-string">'user@192.168.1.1'</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">)</span></span>
<span class="line"></span>
<span class="line">@<span class="token function">task</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'foo'</span><span class="token punctuation">,</span> <span class="token punctuation">[</span><span class="token string single-quoted-string">'on'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'web'</span><span class="token punctuation">]</span><span class="token punctuation">)</span></span>
<span class="line">    ls <span class="token operator">-</span>la</span>
<span class="line">@endtask</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>如你所见， <code v-pre>@servers</code> 的数组被定义在文件的起始位置处，让你在声明任务时可以在 <code v-pre>on</code> 选项里参照使用这些服务器。在你的 <code v-pre>@task</code> 声明里，你可以放置当任务运行时想要在远程服务器运行的 Bash 命令。</p>
<p>你可以通过指定服务器的 IP 地址为 <code v-pre>127.0.0.1</code> 来执行本地任务：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line">@<span class="token function">servers</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token string single-quoted-string">'localhost'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'127.0.0.1'</span><span class="token punctuation">]</span><span class="token punctuation">)</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><h3 id="任务启动" tabindex="-1"><a class="header-anchor" href="#任务启动"><span>任务启动</span></a></h3>
<p>有时，你可能想在任务启动前运行一些 PHP 代码。这时可以使用 <code v-pre>@setup</code> 区块在 Envoy 文件中声明变量以及运行普通的 PHP 程序：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line">@<span class="token class-name type-declaration">setup</span></span>
<span class="line">    <span class="token variable">$now</span> <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">DateTime</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">    <span class="token variable">$environment</span> <span class="token operator">=</span> <span class="token keyword">isset</span><span class="token punctuation">(</span><span class="token variable">$env</span><span class="token punctuation">)</span> <span class="token operator">?</span> <span class="token variable">$env</span> <span class="token punctuation">:</span> <span class="token string double-quoted-string">"testing"</span><span class="token punctuation">;</span></span>
<span class="line">@endsetup</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>如果你想在任务执行前引入其他 PHP 文件，可以直接在 <code v-pre>Envoy.blade.php</code> 文件起始位置使用 <code v-pre>@include</code> ：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line">@<span class="token keyword">include</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'vendor/autoload.php'</span><span class="token punctuation">)</span></span>
<span class="line"></span>
<span class="line">@<span class="token function">task</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'foo'</span><span class="token punctuation">)</span></span>
<span class="line">    <span class="token comment"># ...</span></span>
<span class="line">@endtask</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="任务变量" tabindex="-1"><a class="header-anchor" href="#任务变量"><span>任务变量</span></a></h3>
<p>如果需要的话，你也可以通过命令行选项来传递变量至 Envoy 文件，以便自定义你的任务：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line">envoy run deploy <span class="token operator">--</span>branch<span class="token operator">=</span>master</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>你可以通过 Blade 的「echo」语法使用这些选项， 当然也能在任务里用「if」 和循环操作。举例来说，我们在执行 <code v-pre>git pull</code> 命令前，先检查 <code v-pre>$branch</code> 变量是否存在：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line">@<span class="token function">servers</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token string single-quoted-string">'web'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'192.168.1.1'</span><span class="token punctuation">]</span><span class="token punctuation">)</span></span>
<span class="line"></span>
<span class="line">@<span class="token function">task</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'deploy'</span><span class="token punctuation">,</span> <span class="token punctuation">[</span><span class="token string single-quoted-string">'on'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'web'</span><span class="token punctuation">]</span><span class="token punctuation">)</span></span>
<span class="line">    cd site</span>
<span class="line"></span>
<span class="line">    @<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token variable">$branch</span><span class="token punctuation">)</span></span>
<span class="line">        git pull origin <span class="token punctuation">{</span><span class="token punctuation">{</span> <span class="token variable">$branch</span> <span class="token punctuation">}</span><span class="token punctuation">}</span></span>
<span class="line">    @<span class="token keyword">endif</span></span>
<span class="line"></span>
<span class="line">    php artisan migrate</span>
<span class="line">@endtask</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="任务故事" tabindex="-1"><a class="header-anchor" href="#任务故事"><span>任务故事</span></a></h3>
<p>任务故事通过一个统一的、便捷的名字来划分一组任务，来让你把小而专的子任务合并到大的任务里。比如说，一个名为 <code v-pre>deploy</code> 的任务故事可以在它定义范围内列出子任务名字 <code v-pre>git</code> 和 <code v-pre>composer</code> 来运行各自对应的任务：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line">@<span class="token function">servers</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token string single-quoted-string">'web'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'192.168.1.1'</span><span class="token punctuation">]</span><span class="token punctuation">)</span></span>
<span class="line"></span>
<span class="line">@<span class="token function">story</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'deploy'</span><span class="token punctuation">)</span></span>
<span class="line">    git</span>
<span class="line">    composer</span>
<span class="line">@endstory</span>
<span class="line"></span>
<span class="line">@<span class="token function">task</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'git'</span><span class="token punctuation">)</span></span>
<span class="line">    git pull origin master</span>
<span class="line">@endtask</span>
<span class="line"></span>
<span class="line">@<span class="token function">task</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'composer'</span><span class="token punctuation">)</span></span>
<span class="line">    composer install</span>
<span class="line">@endtask</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>当 story 写好后，像运行普通任务一样运行它就好了：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line">envoy run deploy</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><h3 id="多个服务器" tabindex="-1"><a class="header-anchor" href="#多个服务器"><span>多个服务器</span></a></h3>
<p>你可以在多个服务器上运行任务。首先，增加额外的服务器至你的 <code v-pre>@servers</code> 声明，每个服务器必须分配一个唯一的名称。一旦你定义好其它服务器，就能够在任务声明的 <code v-pre>on</code> 数组中列出这些服务器：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line">@<span class="token function">servers</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token string single-quoted-string">'web-1'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'192.168.1.1'</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'web-2'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'192.168.1.2'</span><span class="token punctuation">]</span><span class="token punctuation">)</span></span>
<span class="line"></span>
<span class="line">@<span class="token function">task</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'deploy'</span><span class="token punctuation">,</span> <span class="token punctuation">[</span><span class="token string single-quoted-string">'on'</span> <span class="token operator">=></span> <span class="token punctuation">[</span><span class="token string single-quoted-string">'web-1'</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'web-2'</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">)</span></span>
<span class="line">    cd site</span>
<span class="line">    git pull origin <span class="token punctuation">{</span><span class="token punctuation">{</span> <span class="token variable">$branch</span> <span class="token punctuation">}</span><span class="token punctuation">}</span></span>
<span class="line">    php artisan migrate</span>
<span class="line">@endtask</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h4 id="并行运行" tabindex="-1"><a class="header-anchor" href="#并行运行"><span>并行运行</span></a></h4>
<p>默认情况下，任务会按照顺序在每个服务器上运行。这意味着任务会在第一个服务器运行完后才跳到第二个。如果你想在多个服务器上并行运行任务，只需简单的在任务声明里加上 <code v-pre>parallel</code> 选项即可：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line">@<span class="token function">servers</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token string single-quoted-string">'web-1'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'192.168.1.1'</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'web-2'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'192.168.1.2'</span><span class="token punctuation">]</span><span class="token punctuation">)</span></span>
<span class="line"></span>
<span class="line">@<span class="token function">task</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'deploy'</span><span class="token punctuation">,</span> <span class="token punctuation">[</span><span class="token string single-quoted-string">'on'</span> <span class="token operator">=></span> <span class="token punctuation">[</span><span class="token string single-quoted-string">'web-1'</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'web-2'</span><span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'parallel'</span> <span class="token operator">=></span> <span class="token constant boolean">true</span><span class="token punctuation">]</span><span class="token punctuation">)</span></span>
<span class="line">    cd site</span>
<span class="line">    git pull origin <span class="token punctuation">{</span><span class="token punctuation">{</span> <span class="token variable">$branch</span> <span class="token punctuation">}</span><span class="token punctuation">}</span></span>
<span class="line">    php artisan migrate</span>
<span class="line">@endtask</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h2 id="运行任务" tabindex="-1"><a class="header-anchor" href="#运行任务"><span>运行任务</span></a></h2>
<p>要想运行一个在 <code v-pre>Envoy.blade.php</code> 文件中定义好的任务或者故事，就执行 Envoy 的 <code v-pre>run</code> 命令，并将这个任务的名字传递给它。Envoy 会去执行这个任务并且把任务执行过程中的输出给打印出来：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line">envoy run task</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><h3 id="任务确认" tabindex="-1"><a class="header-anchor" href="#任务确认"><span>任务确认</span></a></h3>
<p>如果你想要在运行任务之前进行提示确认，则可以增加 <code v-pre>confirm</code> 命令到任务声明。这个选项对于破坏性的操作来说是相当有用的：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line">@<span class="token function">task</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'deploy'</span><span class="token punctuation">,</span> <span class="token punctuation">[</span><span class="token string single-quoted-string">'on'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'web'</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'confirm'</span> <span class="token operator">=></span> <span class="token constant boolean">true</span><span class="token punctuation">]</span><span class="token punctuation">)</span></span>
<span class="line">    cd site</span>
<span class="line">    git pull origin <span class="token punctuation">{</span><span class="token punctuation">{</span> <span class="token variable">$branch</span> <span class="token punctuation">}</span><span class="token punctuation">}</span></span>
<span class="line">    php artisan migrate</span>
<span class="line">@endtask</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h2 id="通知" tabindex="-1"><a class="header-anchor" href="#通知"><span>通知</span></a></h2>
<h3 id="slack" tabindex="-1"><a class="header-anchor" href="#slack"><span>Slack</span></a></h3>
<p>Envoy 也支持任务执行完毕后发送通知至 <a href="https://slack.com/" target="_blank" rel="noopener noreferrer">Slack</a>。<code v-pre>@slack</code> 命令接收 Slack hook 网址和频道名称。你可以通在在 Slack 的控制面板上创建 「Incoming WebHooks」 时来检索 webhook 网址。webhook-url 参数必须是 <code v-pre>@slack</code> 的 Incoming WebHooks 所提供的完整网址：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line">@finished</span>
<span class="line">    @<span class="token function">slack</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'webhook-url'</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'#bots'</span><span class="token punctuation">)</span></span>
<span class="line">@endfinished</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>你可以选择下方的任意一个来作为 channel 参数：</p>
<ul>
<li>如果要发送通知至一个频道： <code v-pre>#channel</code></li>
<li>如果要发送通知给一位用户： <code v-pre>@user</code></li>
</ul>
<h2 id="译者署名" tabindex="-1"><a class="header-anchor" href="#译者署名"><span>译者署名</span></a></h2>
<table>
<thead>
<tr>
<th>用户名</th>
<th>头像</th>
<th>职能</th>
<th>签名</th>
</tr>
</thead>
<tbody>
<tr>
<td><a href="https://phphub.org/users/11602" target="_blank" rel="noopener noreferrer">@司维</a></td>
<td><img src="https://cdn.learnku.com/uploads/avatars/11602_1487572457.png?imageView2/1/w/380/h/380" alt="380"></td>
<td>翻译</td>
<td><a href="https://github.com/leon0204" target="_blank" rel="noopener noreferrer">@leon0204</a> at Github</td>
</tr>
</tbody>
</table>
<hr>
<blockquote>
<p>{note} 欢迎任何形式的转载，但请务必注明出处，尊重他人劳动共创开源社区。</p>
<p>转载请注明：本文档由 Laravel China 社区 <a href="https://laravel-china.org/" target="_blank" rel="noopener noreferrer">laravel-china.org</a> 组织翻译，详见 <a href="https://learnku.com/laravel/t/5756/laravel-55-document-translation-call-come-and-join-the-translation" target="_blank" rel="noopener noreferrer">翻译召集帖</a>。</p>
<p>文档永久地址： <a href="https://learnku.com/docs/laravel" target="_blank" rel="noopener noreferrer">《Laravel 中文文档》</a></p>
</blockquote>
</div></template>


